<template>
  <div
    class="drop-zone"
    :class="{
      'drop-zone--active': isActive,
      'drop-zone--filled': isFilled,
      'drop-zone--correct': showResult && isCorrect,
      'drop-zone--incorrect': showResult && !isCorrect
    }"
    @dragover.prevent="handleDragOver"
    @dragleave="handleDragLeave"
    @drop.prevent="handleDrop"
  >
    <div v-if="!isFilled" class="drop-zone__placeholder">
      <slot name="placeholder">
        <span class="drop-zone__hint">拖到这里</span>
      </slot>
    </div>
    <div v-else class="drop-zone__content">
      <slot name="content" :value="droppedValue">
        {{ droppedValue }}
      </slot>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed } from 'vue'
import { soundManager } from '@/utils/sound'
import { createShakeEffect } from '@/utils/animation'

interface Props {
  zoneId: string
  acceptedValue?: any
  acceptedType?: string
  showResult?: boolean
}

const props = defineProps<Props>()

const emit = defineEmits<{
  drop: [data: { id: string; value: any; type?: string; correct: boolean }]
}>()

const isActive = ref(false)
const isFilled = ref(false)
const droppedValue = ref<any>(null)
const isCorrect = ref(false)

function handleDragOver(e: DragEvent) {
  isActive.value = true
  e.dataTransfer!.dropEffect = 'move'
}

function handleDragLeave() {
  isActive.value = false
}

function handleDrop(e: DragEvent) {
  isActive.value = false

  try {
    const data = JSON.parse(e.dataTransfer!.getData('application/json'))

    // 检查是否正确
    const correct = checkCorrect(data)
    isCorrect.value = correct

    // 填充区域
    isFilled.value = true
    droppedValue.value = data.value

    // 播放音效
    if (correct) {
      soundManager.playSuccess()
    } else {
      soundManager.playError()
      // 温柔的摇��提示
      const element = e.currentTarget as HTMLElement
      createShakeEffect(element)
    }

    emit('drop', { ...data, correct })
  } catch (error) {
    console.error('处理拖放数据失败:', error)
  }
}

function checkCorrect(data: any): boolean {
  // 如果没有指定接受值，则总是正确
  if (props.acceptedValue === undefined) return true

  // 检查类型
  if (props.acceptedType && data.type !== props.acceptedType) {
    return false
  }

  // 检查值
  return data.value === props.acceptedValue
}

// 重置区域
function reset() {
  isFilled.value = false
  droppedValue.value = null
  isCorrect.value = false
}

// 暴露方法给父组件
defineExpose({
  reset,
  isFilled: computed(() => isFilled.value),
  isCorrect: computed(() => isCorrect.value),
  value: computed(() => droppedValue.value)
})
</script>

<style scoped>
.drop-zone {
  min-width: 100px;
  min-height: 100px;
  border: 3px dashed #ccc;
  border-radius: 16px;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: #f9f9f9;
  transition: all 0.3s ease;
  font-size: 24px;
  font-weight: bold;
}

.drop-zone--active {
  border-color: #4CAF50;
  background-color: #e8f5e9;
  transform: scale(1.05);
}

.drop-zone--filled {
  border-style: solid;
  background-color: #fff;
}

.drop-zone--correct {
  border-color: #4CAF50;
  background-color: #e8f5e9;
}

.drop-zone--incorrect {
  border-color: #ff9800;
  background-color: #fff3e0;
}

.drop-zone__placeholder {
  color: #999;
  font-size: 18px;
  text-align: center;
}

.drop-zone__hint {
  display: block;
  padding: 10px;
}

.drop-zone__content {
  padding: 20px;
  font-size: 32px;
}
</style>
